<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js ie6" lang="en"> <![endif]-->
<!--[if IE 7]>    <html class="no-js ie7" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="no-js ie8" lang="en"> <![endif]-->
<!--[if gt IE 8]><!-->  <html class="no-js" lang="en"> <!--<![endif]-->
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	
	<title>Android で SQLite3 を利用する</title>
	
	<meta name="description" content="Use SQLite3 in Android">
	<meta name="author" content="KOZAKI Tsuneaki">
	<meta name="viewport" content="width=1024, user-scalable=no">
	
	<!-- Core and extension CSS files -->
	<link rel="stylesheet" href="core/deck.core.css">
	<link rel="stylesheet" href="extensions/goto/deck.goto.css">
	<link rel="stylesheet" href="extensions/menu/deck.menu.css">
	<link rel="stylesheet" href="extensions/navigation/deck.navigation.css">
	<link rel="stylesheet" href="extensions/status/deck.status.css">
	<link rel="stylesheet" href="extensions/hash/deck.hash.css">
	
	<!-- Theme CSS files (menu swaps these out) -->
	<link rel="stylesheet" id="style-theme-link" href="themes/style/web-2.0.css">
	<link rel="stylesheet" id="transition-theme-link" href="themes/transition/horizontal-slide.css">
	
	<!-- Custom CSS just for this page -->
	<link rel="stylesheet" href="custom.css">
	
	<script src="modernizr.custom.js"></script>
</head>

<body class="deck-container">

<section class="slide">
	<h1>Androidでデータベース利用</h1>
</section>

<section class="slide">
	<h2>提供</h2>
  <p>本日は</p>
  <ul>
    <li class="slide">ＰＪ推一  小崎</li>
    <li class="slide">Ｓ三Ｅ三  宇野</li>
  </ul>
  <p class="slide">の提供でお送りします</p>
</section>

<section class="slide">
	<h2>謝辞</h2>
  <p>まずは本日の勉強会にお集りいただきありがとうございました</p>
  <p>ちょこっとアプリ作成塾は全社に開かれた塾を目指しています</p>
  <img src="img/gate.jpg" class="slide" alt="" />
</section>

<section class="slide">
	<h2>今日のお題</h2>
  <p>Android アプリでのデータベースアクセスを学びます</p>
  <p>ほんのさわりだけです。サーセン。</p>
  <div class="slide">
  <img src="img/sa-sen.jpg" class="" alt="" />
  </div>
</section>

<section class="slide">
  <h2>アジェンダ</h2>
  <ol>
    <li>Android からデータベースを扱う方法</li>
    <li>今日説明すること</li>
    <li>今日説明しないこと</li>
    <li>ハンズオンチュートリアル</li>
  </ol>
</section>

<section class="slide">
  <h2>Androidからデータベースを扱う方法</h2>
  <p>だいたい以下のような選択肢があります</p>
  <ol>
    <li class="slide">自前でデータベースの作成＆管理をすべてする</li>
    <p class="slide">本日説明するこがこのパターンです。</p>
    <li class="slide">あらかじめデータベースは作成＆インストールしておいて、更新などのみをAndroidでする</li>
    <p class="slide">例えば、辞書データなどをあらかじめ用意するようなケース</p>
    <li class="slide">データベースを扱うバックエンドサーバーを用意して、Android はクライアントに徹する</li>
    <p class="slide">Webアプリを別に作成して、データを JSON などで遣り取りする。</p>
    <p class="slide">データベースのことは考えなくてよくなるけど、代わりにネットワーク関連で考えることが増える。</p>
  </ol>
</section>

<section class="slide">
  <h2>今日説明すること</h2>
  <p>自前でデータベースを用意して、初期データをロード。</p>
  <p>データベースに対して SELECT * FROME table; を発行して、結果を画面に表示する</p>
</section>
  
<section class="slide">
  <h2>今日説明しないこと</h2>
  <p>それ以外</p>
  <p class="slide">Android開発環境のセットアップ</p>
  <p class="slide">画面レイアウトの作成方法</p>
  <p class="slide">SQLite3 とは</p>
  <p class="slide">データベースへの更新、削除</p>
  <p class="slide">画面遷移</p>
  <p class="slide">MORE</p>
  <p class="slide" style="font-size:200%">MORE</p>
  <p class="slide" style="font-size:400%">MORE</p>
</section>
  
<section class="slide">
  <h2>ハンズオンの段取り </h2>
  <ol>
    <li class="slide">
      サンプルアプリケーションの雛形の作成
    </li>
    <li class="slide">
      データベースのスキーマやらSQL文やらを一括して保持するクラスを作成
    </li>
    <li class="slide">
      組込みのSQLiteOpenHelperを継承して、SampleDBHelperクラスを作成
    </li>
    <li class="slide">
      Activity から SampleDBHelper を経由してデータベースにアクセス
    </li>
  </ol>
</section>

<section class="slide">
  <h2>サンプルアプリケーション雛形の作成</h2>
  <img src="img/new_android_project.png" class="" alt="" />
</section>

<section class="slide">
  <h2>サンプルアプリケーション雛形の作成</h2>
  <p>好きに作成して下さい</p>
  <img src="img/new_android_project_name.png" class="" alt="" />
</section>

<section class="slide">
  <h2>サンプルアプリケーション雛形の作成</h2>
  <p>ターゲットは Android 2.3 にしとくか</p>
  <img src="img/new_android_project_build_target.png" class="" alt="" />
</section>

<section class="slide">
  <h2>サンプルアプリケーション雛形の作成</h2>
  <p>パッケージ名とかも自分のプロジェクト用に付けるんだよ。</p>
  <img src="img/new_android_project_property.png" class="" alt="" />
</section>

<section class="slide">
  <h2>出来たら、まずは稼動確認</h2>
  <img src="img/execute_application_small.png" class="" alt="" />
</section>

<section class="slide">
  <h2>動いた？</h2>
  <img src="img/initial_application.png" class="" alt="" />
</section>

<section class="slide">
  <h1>動かない人がいる場合のサポートタイム</h1>
</section>

<section class="slide">
  <h2>重要な注意</h2>
  <p>起動したエミュレータは閉じてはいけません</p>
  <img src="img/dame_zettai.jpg" class="slide" alt="" />
</section>

<section class="slide">
  <h2>適当に画面を作成</h2>
  <p>画面デザインのハンズオンは誰かが、何処かでやるに違いねぇ</p>
  <img src="img/edit_layout_small.png" class="" alt="" />
</section>

<section class="slide">
  <h2>とは言うものの...</h2>
  <ol>
    <li>デフォルトで張り付いているTextViewを編集</li>
    <ol>
      <li>Edit ID... => resultView</li>
      <li>Edit Text... => クリア</li>
      <li>Layout Height => Match Parent</li>
      <li>Property => Layout weight => 10</li>
    </ol>
    <li>「Display」ボタンを追加</li>
    <ol>
      <li>パレットから適当にドラッグ＆ドロップ</li>
      <li>Edit ID... => displayButton</li>
      <li>Edit Text... => Display</li>
      <li>Layout Width => Match Parent</li>
      <li>Property => Layout weight => 1</li>
      <li>Property => OnClick... => displayTable</li>
    </ol>
  </ol>
</section>

<section class="slide">
  <h2>また、動くか確認</h2>
  <p style="text-align:center;font-size:200%;margin-top:5em;">画像は省略</p>
</section>

<section class="slide">
  <h2>ハンズオンの段取り </h2>
  <ol>
    <li style="color:silver;">
      サンプルアプリケーションの雛形の作成
    </li>
    <li>
      データベースのスキーマやらSQL文やらを一括して保持するクラスを作成
    </li>
    <li style="color:silver;">
      組込みのSQLiteOpenHelperを継承して、SampleDBHelperクラスを作成
    </li>
    <li style="color:silver;">
      Activity から SampleDBHelper を経由してデータベースにアクセス
    </li>
  </ol>
</section>

<section class="slide">
  <h2>作ろうとしているテーブル</h2>
  <p>サンプルなのでテーブルは非常にシンプルです。</p>
      <div align="left" style="margin: 1em;">
      <table id="persons">
        <tr>
          <th>カラム名</th><th>タイプ</th>
        </tr>
        <tr>
          <td>name(氏名)</td><td>VARCHAR</td>
        </tr>
        <tr>
          <td>age(年齢)</td><td>INTEGER</td>
        </tr>
      </table>
      </div> 
      <p>なんと、これだけ！</p>
      <p class="slide">ちょっと泣けてきましたね。</p>
</section>

<section class="slide">
  <h2>DBInfo.java (1/3)</h2>
  <pre>
public class DBInfo {
    public static final String DB_NAME = "test.db";
    public static final String TABLE_NAME = "people";
    public static final int VERSION = 1;

    public static final ArrayList&lt;Pair&lt;String, String&gt;&gt; DB_SCHEMA =
        new ArrayList&lt;Pair&lt;String, String&gt;&gt;() { {
            add(new Pair&lt;String, String&gt;("name", "VARCHAR"));
            add(new Pair&lt;String, String&gt;("age", "INTEGER"));
    } };

    public static final ArrayList&lt;Pair&lt;String, Integer&gt;&gt; INITIAL_VALUE =
        new ArrayList&lt;Pair&lt;String, Integer&gt;&gt;() { {
            add(new Pair&lt;String, Integer&gt;("山田 浩一郎", 25));
            add(new Pair&lt;String, Integer&gt;("佐久間 慎吾", 37));
            add(new Pair&lt;String, Integer&gt;("天城 京子", 18));
    } };
...
  </pre>
</section>

<section class="slide">
  <h2>DBInfo.java (2/3)</h2>
  <pre>
    public static String createTable() {
        String create_statement = "CREATE TABLE " + TABLE_NAME + " (" +
            "_id INTEGER PRIMARY KEY AUTOINCREMENT, ";
        for(Pair&lt;String, String&gt; column : DB_SCHEMA) {
            create_statement += column.first + " " + column.second + ", ";
        }
        return create_statement.replaceAll(", $", ");");
    }

    public static List&lt;String&gt; insertStatements() {
        ArrayList&lt;String&gt; insert_statements = new ArrayList&lt;String&gt;();
        String insert_statement = "INSERT INTO " + TABLE_NAME + " (";
        for(Pair&lt;String, String&gt; column : DB_SCHEMA) {
            insert_statement += column.first + ", ";
        }
        insert_statement = insert_statement.replaceAll(", $", ") VALUES (");
        for(Pair&lt;String, Integer&gt; value : INITIAL_VALUE) {
            insert_statements.add(insert_statement + "'" + value.first + "', " +
                                  value.second + ");");
        }
        return insert_statements;
    }
  </pre>
</section>

<section class="slide">
  <h2>DBInfo.java (3/3)</h2>
  <pre>
...
    public static String selectAll() {
        String select_statement = "SELECT ";
        for(Pair&lt;String, String&gt; column : DB_SCHEMA) {
            select_statement += column.first + ", ";
        }
        return select_statement.replaceAll(", $", " FROM ") + TABLE_NAME + ";";
    }

    public static String[] columns() {
        ArrayList&lt;String&gt; columns = new ArrayList&lt;String&gt;();
        for(Pair&lt;String, String&gt; column : DB_SCHEMA) {
            columns.add(column.first);
        }
        return columns.toArray(new String[0]);
    }
}
  </pre>
</section>

<section class="slide">
  <h1>コードに文句がある人は自前で修正して下さい</h1>
</section>

<section class="slide">
  <h2>ハンズオンの段取り </h2>
  <ol>
    <li style="color:silver;">
      サンプルアプリケーションの雛形の作成
    </li>
    <li style="color:silver;">
      データベースのスキーマやらSQL文やらを一括して保持するクラスを作成
    </li>
    <li>
      組込みのSQLiteOpenHelperを継承して、SampleDBHelperクラスを作成
    </li>
    <li style="color:silver;">
      Activity から SampleDBHelper を経由してデータベースにアクセス
    </li>
  </ol>
</section>

<section class="slide">
  <h2>SampleDBHelper.java</h2>
  <pre>
public class SampleDBHelper extends SQLiteOpenHelper {

    public SampleDBHelper(Context context) {
        super(context, DBInfo.DB_NAME, null, DBInfo.VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DBInfo.createTable());
        for(String insert_statement : DBInfo.insertStatements()) {
            db.execSQL(insert_statement);
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldv, int newv) {
    }
}
  </pre>
</section>

<section class="slide">
  <h2>ちょっと解説</h2>
  <ul>
    <li class="slide">
      コンストラクタでDBHelperが接続するDB、そのバージョンを指定。第三引数はよくわからん。
    </li>
    <li class="slide">
      第四引数がデータベースのバージョン。アプリをリリースした後、テーブルのスキーマが変わる場合、このバージョン番号を上げる
    </li>
    <li class="slide">
      onCreate()がデータベースが存在しない時に実行される。このタイミングでテーブルを作成する
    </li>
    <p class="slide">今回はここで初期データをロードした。もちろん必須ではないよ</p>
    <p class="slide">トランザクション？知らんな</p>
    <p class="slide">後で説明する adb shell からテーブルを drop したりするとデータベースだけ存在する状態になって、テーブルが再度作成されないので注意</p>
    <li class="slide">
      onUpgrade()はデータベースのバージョンが変わった場合に実行される
    </li>
    <p class="slide">ここにマイグレーションコードを書くわけですが、とりあえず当分気にしないことにした</p>
  </ul>
</section>

<section class="slide">
  <h2>ハンズオンの段取り </h2>
  <ol>
    <li style="color:silver;">
      サンプルアプリケーションの雛形の作成
    </li>
    <li style="color:silver;">
      データベースのスキーマやらSQL文やらを一括して保持するクラスを作成
    </li>
    <li style="color:silver;">
      組込みのSQLiteOpenHelperを継承して、SampleDBHelperクラスを作成
    </li>
    <li>
      Activity から SampleDBHelper を経由してデータベースにアクセス
    </li>
  </ol>
</section>

<section class="slide">
  <h2>SQLiteSampleActivity.java</h2>
  <pre>
public class SQLiteSampleActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    public void displayTable(View v) {
        TextView view = (TextView)findViewById(R.id.resultView);
        SQLiteDatabase db = (new SampleDBHelper(this)).getReadableDatabase();
        Cursor c = db.query(DBInfo.TABLE_NAME, DBInfo.columns(), null,
                            null, null, null, null);
        view.setText("Table contents\n");
        view.append("--------------------------------------\n");
        while (c.moveToNext()) {
            view.append(String.format("%s\t%d\n",
                                      c.getString(0), c.getInt(1)));
        }
        c.close();
        db.close();
    }
}
  </pre>
</section>

<section class="slide">
  <h2>動きましたか？</h2>
  <img src="img/finished_appli.png" class="" alt="" />
</section>

<section class="slide">
  <h1>動かない人がいる場合のサポートタイム２</h1>
</section>

<section class="slide">
  <h2>レコードを追加してみよう</h2>
  <p>画面がないので、コンソールから追加してみます。emulatorが起動した状態で次のコマンドを実行</p>
  <pre>
    $ adb shell
  </pre>
</section>

<section class="slide">
  <h2>味も素気もないプロンプトが出ましたか？</h2>
  <pre>
    # cd data/data/com.sample.kokou/databases
    # ls
    test.db
  </pre>
  <p> com.sample.kokouの所は自分の作成したパッケージ名に置き換えて下さい</p>
</section>

<section class="slide">
  <h2>test.db見付かりましたか？</h2>
  <pre>
    # sqlite3 test.db
    SQLite version 3.6.22
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
    sqlite> 
  </pre>
</section>

<section class="slide">
  <h2>peopleテーブル見付かりましたか？</h2>
  <pre>
    sqlite> .schema people
    CREATE TABLE people (_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, age INTEGER);
  </pre>
</section>

<section class="slide">
  <h2>レコードを追加してみましょう</h2>
  <pre>
    sqlite> INSERT INTO people (name, age) VALUES ('白石 亜希子', 42);
    sqlite> .q
    # exit
  </pre>
</section>

<section class="slide">
  <h2>レコードが追加されていますか？</h2>
  <img src="img/after_insert_table.png" class="" alt="" />
</section>


<section class="slide">
  <h2>お疲れさまでした</h2>
  <div style="text-align: center;margin:5em;">
    <img src="img/pekori.jpg" class="" alt="<(_ _)>" />
  </div>
  <h2 class="slide" align="center" style="color:#f0f;">第一部  完！</h2>
</section>

<section class="slide">
  <h2>第二部  課題</h2>
  <p>余った時間を利用して次のような課題に挑戦してみましょう。</p>
  <ol>
    <li>テーブルの表示をちゃんとしたものにする</li>
    <li>レコードの新規登録をする画面を追加する</li>
    <li>クリックすると、編集用の画面に遷移してレコードを編集する</li>
    <li>長押しすると、確認ダイアログを表示してレコードを削除する</li>
    <li>O/R Mapper を利用してみる</li>
  </ol>
</section>

<section class="slide">
  <h2>ListViewでテーブルの内容を表示する</h2>
  <p>ListViewを使うと、一覧表示がそれらしい雰囲気になります</p>
  <img src="img/list_view.png" class="" alt="" />
  <h3 class="slide">難易度 : 普通</h3>
</section>

<section class="slide">
  <h2>レコードを新規登録できるようにする</h2>
  <p>adb shell で追加するのは大変なので、登録用の画面を作りましょう</p>
  <img src="img/new_person_button.png" class="" alt="" />
</section>

<section class="slide">
  <h2>もう一枚画面を作って遷移する</h2>
  <img src="img/new_person_view.png" class="" alt="" />
</section>

<section class="slide">
  <h2>登録したら元の画面に戻る</h2>
  <img src="img/new_person_input.png" class="" alt="" />
</section>

<section class="slide">
  <h2>レコードが追加されているね</h2>
  <img src="img/list_persons_view.png" class="" alt="" />
  <p>…て感じ。</p>
  <h3 class="slide">難易度 : 易</h3>
</section>

<section class="slide">
  <h2>一覧から行をクリックして編集する</h2>
  <p>こんどは好きな行をクリック</p>
  <img src="img/edit_person.png" class="" alt="" />
</section>

<section class="slide">
  <h2>編集画面に遷移</h2>
  <p>新規登録と同じ画面やん。。。</p>
  <img src="img/edit_view.png" class="" alt="" />
  <p>この後の動きも同じ。（`・ω・´）ｷﾘｯ</p>
  <h3 class="slide">難易度 : 普通</h3>
</section>

<section class="slide">
  <h2>一覧から行を長押しして削除する</h2>
  <p>こんどは長めに押す。だんだんエミュレータでは辛くなってきましたね</p>
  <img src="img/long_press_person.png" class="" alt="" />
</section>

<section class="slide">
  <h2>確認ダイアログを出す</h2>
  <p>長押しで何をするかユーザーにわからんので説明のダイアログを出す</p>
  <img src="img/confirm_dialog.png" class="" alt="" />
</section>

<section class="slide">
  <h2>削除されていることを確認</h2>
  <p>OK を押すとレコードが削除されている</p>
  <img src="img/complete_to_delete.png" class="" alt="" />
  <h3 class="slide">難易度 : 普通</h3>
</section>

<section class="slide">
  <h2>DBInfo.java がダサすぎる</h2>
  <p>こんな感じにしたい</p>
  <pre>
@DatabaseTable(tableName = "people")
public class Person {
    @DatabaseField(generatedId = true)
    int _id;
    @DatabaseField
    String name;
    @DatabaseField
    int age;

    public void setName(String name) { this.name = name; }
    public String getName() { return this.name; }

    public void setAge(int age) { this.age = age; }
    public int getAge() { return this.age; }

    Person() { /* use ormlite */ }
    }
}
  </pre>
</section>
<section class="slide">
  <h2>さっきのコードはOrmLiteというパッケージ</h2>
  <p>参照 : <a href="http://ormlite.com/">OrmLite</a> </p>
  <img src="" class="" alt="" />
  <h3 class="slide">難易度 : あなたの英語力次第</h3>
</section>

<section class="slide">
  <h2>サンプルコード</h2>
  <p>画面のハードコピーがあるということは、作ったということです</p>
  <p>googlecode:<a href="http://code.google.com/p/sqlite-android-sample/">sqlite-android-sample</a></p>
</section>

<a href="#" class="deck-prev-link" title="Previous">&#8592;</a>
<a href="#" class="deck-next-link" title="Next">&#8594;</a>

<p class="deck-status">
	<span class="deck-status-current"></span>
	/
	<span class="deck-status-total"></span>
</p>

<form action="." method="get" class="goto-form">
	<label for="goto-slide">Go to slide:</label>
	<input type="number" name="slidenum" id="goto-slide">
	<input type="submit" value="Go">
</form>

<a href="." title="Permalink to this slide" class="deck-permalink">#</a>


  <!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
  <script>window.jQuery || document.write('<script src="jquery-1.6.4.min.js"><\/script>')</script>

<!-- Deck Core and extensions -->
<script src="core/deck.core.js"></script>
<script src="extensions/menu/deck.menu.js"></script>
<script src="extensions/goto/deck.goto.js"></script>
<script src="extensions/status/deck.status.js"></script>
<script src="extensions/navigation/deck.navigation.js"></script>
<script src="extensions/hash/deck.hash.js"></script>

<!-- Specific to this page -->
<script src="custom.js"></script>

</body>
</html>
